import numpy as np
import matplotlib.pyplot as plt

# 1. 散点输入
data = np.array([
    [0.8, 0],
    [1.1, 0],
    [1.7, 0],
    [3.2, 1],
    [3.7, 1],
    [4.0, 1],
    [4.2, 1]
])
x_data = data[:, 0]
y_data = data[:, 1]


# 2. 期望函数
# y = w * x + b 是一条直线，引入sigmoid之后，没有实际意义了

# 3. 引入sigmoid函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))


# 4. 超参数 和 参数初始化
lr = 0.5
Epochs = 2000
w = 0
b = 0

fig = plt.figure("show Logistic regression", figsize=(12, 6))
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
epoch_list = []
loss_list = []

# 5. 循环训练
for epoch in range(Epochs):
    # 前向传播
    z = w * x_data + b
    a = sigmoid(z)
    # 计算损失
    loss = np.mean((y_data - a) ** 2)
    # 反向传播(根据链式法则，计算梯度)
    deda = -2 * (y_data - a)
    dadz = a * (1 - a)
    dzdw = x_data
    dzdb = 1
    gd_w = np.mean(deda * dadz * dzdw)
    gd_b = np.mean(deda * dadz * dzdb)
    # 更新参数
    w = w - lr * gd_w
    b = b - lr * gd_b

    epoch_list.append(epoch)
    loss_list.append(loss)

    # 打印信息
    if epoch == 0 or (epoch + 1) % 10 == 0:
        print(f"[{epoch + 1}/{Epochs}] w:{round(w, 3)} b:{round(b, 3)} Loss:{round(loss, 3)}")
        ax1.clear()
        ax1.scatter(x_data, y_data, c='b', s=50)
        x_min, x_max = x_data.min(), x_data.max()
        x_values = np.linspace(x_min, x_max, int(x_max - x_min) * 10)
        y_values = np.round(sigmoid(w * x_values + b), 3)
        ax1.plot(x_values, y_values, 'r-', lw=3)
        # ax2.clear()
        # ax2.plot(x_data, a, 'r-', lw=3)

        plt.pause(0.1)

    ax2.plot(epoch_list, loss_list, 'r-', lw=3)

plt.show()

# 6. 画图
# 学生练习，绘制动态拟合图（循环更新）——散点图和曲线
# 学生练习，损失曲线图
